package ui;

import java.util.Scanner;

import core.access.Read;
import core.access.Write;
import core.cwm.COI;
import core.cwm.COISet;
import core.cwm.CompanyRecord;
import core.obj.Object;
import core.sub.Company;
import core.sub.Subject;

import security.acl.AccessController;
import security.msg.ErrorMessage;
import security.msg.InfoMessage;
import security.msg.Message;
import util.Constants;

public class MACS6 {
	private Scanner input;
	
	public MACS6() {
		input = new Scanner(System.in);
	}
	
	public void start() {
		AccessController.getInstance().initialize();
		
		printPrompt();
		String str = input.nextLine();
		String[] tokens = str.split(" ");
		while(!tokens[0].equals(Constants.QUIT_OPER_UI)) {
			// Process the command
			if(tokens[0].equals(Constants.LIST_OPER_UI)) {
				processListOperation(tokens);
			} else if(tokens[0].equals(Constants.READ_OPER_UI)) {
				processReadOperation(tokens);
			} else if(tokens[0].equals(Constants.WRITE_OPER_UI)) {
				processWriteOperation(tokens);
			} else if(tokens[0].equals(Constants.APPLY_OPER_UI)) {
				processApplyOperation(tokens);
			} else if(tokens[0].equals(Constants.SHOW_OPER_UI)) {
				processShowOperation(tokens);
			} else if(tokens[0].equals(Constants.ADD_OPER_UI)) {
				processAddOperation(tokens);
			}
			
			printPrompt();
			str = input.nextLine();
			tokens = str.split(" ");
		}
	}
	
	private void printPrompt() {
		String prompt = ">>> ";
		System.out.print(prompt);
	}
	
	private void processReadOperation(String[] tokens) {
		Message msg = null;
		AccessController acl = AccessController.getInstance();
		if(tokens.length != 3) {
			msg = new ErrorMessage(ErrorMessage.READ_FORMAT_ERROR);
		} else {
			String subID = tokens[1];
			String objID = tokens[2];
			Subject sub = acl.getSubject(subID);
			Object obj = acl.findObject(objID);
			if(sub != null && obj != null) {
				msg = acl.access(sub, obj, Read.getRight());
			} else {
				msg = new InfoMessage();
			}
		}
		System.out.println(msg.printMsg());
	}
	
	private void processWriteOperation(String[] tokens) {
		Message msg = null;
		AccessController acl = AccessController.getInstance();
		if(tokens.length != 3) {
			msg = new ErrorMessage(ErrorMessage.WRITE_FORMAT_ERROR);
		} else {
			String subID = tokens[1];
			String objID = tokens[2];
			Subject sub = acl.getSubject(subID);
			Object obj = acl.findObject(objID);
			if(sub != null && obj != null) {
				msg = acl.access(sub, obj, Write.getRight());
				if(!(msg instanceof ErrorMessage)) {
					String data = input.nextLine();
					acl.writeObject(obj, data);
					msg.setContent("Successful write to "+objID+": " +data);
				}
			} else {
				msg = new InfoMessage();
				msg.setContent("Can not find "+subID+" and "+objID);
			}
		}
		System.out.println(msg.printMsg());
	}
	
	private void processApplyOperation(String[] tokens) {
		Message msg = null;
		AccessController acl = AccessController.getInstance();
		if(tokens.length != 3) {
			msg = new ErrorMessage(ErrorMessage.APPLY_FORMAT_ERROR);
		} else {
			String subID = tokens[1];
			String companyID = tokens[2];
			Subject sub = acl.getSubject(subID);
			Company company = acl.getCompany(companyID);
			msg = acl.apply(sub, company);		
		}
		System.out.println(msg.printMsg());
	}
	
	private void processShowOperation(String[] tokens) {
		Message msg = null;
		if(tokens.length != 2) {
			msg = new ErrorMessage(ErrorMessage.SHOW_FORMAT_ERROR);
		} else {
			msg = new InfoMessage();
			String coiID = tokens[1];
			COI coi = COISet.getInstance().getCOI(coiID);
			if(coi != null) {
				String str = "";
				for(Company C: coi.getCompanies()) {
					str += C.getID() + "\n";
				}
				msg.setContent(str);
			} else {
				msg.setContent("Can not find "+coiID);
			}
		}
		System.out.println(msg.printMsg());
	}
	
	private void processAddOperation(String[] tokens) {
		Message msg = null;
		if(tokens.length < 3) {
			msg = new ErrorMessage(ErrorMessage.SHOW_FORMAT_ERROR);
		} else {
			msg = new InfoMessage();
			if(tokens[1].equals(Constants.COI_UI)) {
				// Add COI
				String coiID = tokens[2];
				String compID = null;
				COI coi = COISet.getInstance().getCOI(coiID);
				if(coi == null) {
					coi = new COI(coiID);
					for(int i = 3;i<tokens.length;i++) {
						compID = tokens[i];
						Company company = CompanyRecord.getInstance().lookup(compID);
						if(company != null) {
							coi.add(company);
						}
					}
					AccessController.getInstance().addCOI(coi);
				}
				msg.setContent("Add COI "+coiID);
			}
		}
		System.out.println(msg.printMsg());
	}	
	
	private void processListOperation(String[] tokens) {
		Message msg = null;
		AccessController acl = AccessController.getInstance();
		if(tokens.length != 2) {
			msg = new ErrorMessage(ErrorMessage.LIST_ERROR);
		} else {
			msg = new InfoMessage();
			if(tokens[1].equals(Constants.COMPANY_SUB_UI)) {
				msg.setContent(acl.showSubjects(Constants.COMPANY_SUB));
			} else if(tokens[1].equals(Constants.EMPLOYEE_SUB_UI)) {
				msg.setContent(acl.showSubjects(Constants.EMPLOYEE_SUB));
			} else if(tokens[1].equals(Constants.CONTRACTOR_SUB_UI)) {
				msg.setContent(acl.showSubjects(Constants.CONTRACTOR_SUB));
			} else if(tokens[1].equals(Constants.EMPLOYEE_CONTRACTOR_SUB_UI)) {
				msg.setContent(acl.showSubjects(Constants.EMPLOYEE_CONTRACTOR_SUB));
			} else if(tokens[1].equals(Constants.INVOICE_OBJ_UI)) {
				msg.setContent(acl.showObjects(Constants.INVOICE_OBJ));
			} else if(tokens[1].equals(Constants.PAYCHECK_OBJ_UI)) {
				msg.setContent(acl.showObjects(Constants.PAYCHECK_OBJ));
			} else if(tokens[1].equals(Constants.PAYMENT_OBJ_UI)) {
				msg.setContent(acl.showObjects(Constants.PAYMENT_OBJ));
			} else if(tokens[1].equals(Constants.RESUME_OBJ_UI)) {
				msg.setContent(acl.showObjects(Constants.RESUME_OBJ));
			} else if(tokens[1].equals(Constants.STAFF_REG_OBJ_UI)) {
				msg.setContent(acl.showObjects(Constants.STAFF_REQ_OBJ));
			} else if(tokens[1].equals(Constants.TIME_REPORT_OBJ_UI)) {
				msg.setContent(acl.showObjects(Constants.TIME_REPORT_OBJ));
			} else if(tokens[1].equals(Constants.COI_UI)) {
				msg.setContent(acl.showCOIs());
			} 
		}
		System.out.println(msg.printMsg());
	}
	
	public void test() {
		AccessController.getInstance().initialize();
		String[] case1 = {"read","E4","SR1"};
		String[] case2 = {"read","E4","SR5"};
		String[] case3 = {"read","E4","SR2"};
		String[] case4 = {"read","E4","SR3"};
		String[] case5 = {"read","E4","SR5"};
		String[] case6 = {"read","E4","SR6"};
		String[] case7 = {"read","E4","SR4"};
		processReadOperation(case1);
		processReadOperation(case2);
		processReadOperation(case3);
		processReadOperation(case4);
		processReadOperation(case5);
		processReadOperation(case6);
		processReadOperation(case7);
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MACS6 program = new MACS6();
		program.start();
//		program.test();
	}

}
